using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using Framework.EventArg;
using System.Reflection;
using Framework.MyAtrribute;
using Framework.ObjectPool;
/// <summary>
/// 面板基类
/// </summary>

public class PanelBase : MonoBehaviour
{

    public bool ifBlockTimeFlow = false;//是否禁流时间
    public bool isTemp = false;//是否是临时对象（默认否）
    public string ObjectType = "";//对象池
    public PanelShowStyle showStyle = PanelShowStyle.None;
    public Transform trans_content;//会受到ShowStyle影响的面板内容
    public Button btn_close;//关闭按钮
    //按钮点击事件字典
    public Dictionary<Button, UnityEngine.Events.UnityAction> btnListenerDic = new Dictionary<Button, UnityEngine.Events.UnityAction>();

    private Dictionary<int, List<Action<EventArg>>> DATA_UIEvtDic = new Dictionary<int, List<Action<EventArg>>>();//数据-UI层事件
    private Dictionary<int, List<Action<EventArg>>> UI_UIEvtDic = new Dictionary<int, List<Action<EventArg>>>();//UI-UI事件
    /// <summary>
    /// 面板指引监听
    /// </summary>
    List<int> guideListenerList = new List<int>();
    /// <summary>
    /// 该面板当前进行的指引id
    /// </summary>
    int curFocusedGuideId = 0;
    /// </summary>
    //带参数字典
    //public Dictionary<Button, Action<object[]>> btnListenerWithParaDic = new Dictionary<Button, Action<object[]>>()
    //public PanelStyle tanChuangStyle = PanelStyle.Scale;//弹窗风格
    //面板缩放参数
    static float PanelScaleVal = 1.1f;
    static float PanelScaleTime = 0.25f;//动画时间
    static float PanelScaleBackTime = 0.2f;

    /// <summary>
    /// 页面被创建时触发该方法
    /// </summary>
    public  void UIInit()
    {
        //Debug.Log("页面创建触发");
        _initDataListener();
        _initUIListener();
    }
    /// <summary>
    /// 初始化数据监听
    /// </summary>
    private void _initDataListener()
    {
        DATA_UIEvtDic.Clear();
        var bindingFlag = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
        var mMethods = this.GetType().GetMethods(bindingFlag);
        foreach (var mMethodInfo in mMethods)
        {
            var mAttrObjs = mMethodInfo.GetCustomAttributes(typeof(DataListenerAttribute), false);
            if (mAttrObjs.Length > 0)
            {
                var mAttrObj = mAttrObjs[0] as DataListenerAttribute;
                var methodParameters = mMethodInfo.GetParameters();
                if (methodParameters.Length < 1)
                {
                    Debug.LogError("[DataListenerAttribute] 指定方法不符合规定，未声明传参（EventArg） : " + mMethodInfo.Name, this);
                    return;
                }
                else if (methodParameters.Length == 1 & methodParameters[0].ParameterType == typeof(EventArg))
                {
                    Action<EventArg> action = (EventArg rArg) => { mMethodInfo.Invoke(this, new object[] { rArg }); };
                    //viewManager.EventManager.BindEvent(mAttrObj.EventCode, action);
                    AddEventToDataListener(mAttrObj.evtCode, action);
                }
                else
                {
                    Debug.LogError("[DataListenerAttribute] 指定方法不符合规定，只能声明传参（EventArg） : " + mMethodInfo.Name, this);
                    return;
                }
            }
        }
    }

    /// <summary>
    /// 绑定事件
    /// </summary>
    /// <param name="code"></param>
    /// <param name="action"></param>
    private void AddEventToDataListener(int code, Action<EventArg> action)
    {
        if (!this.DATA_UIEvtDic.ContainsKey(code))
            this.DATA_UIEvtDic[code] = new List<Action<EventArg>>();
        this.DATA_UIEvtDic[code].Add(action);
    }

    /// <summary>
    /// 初始化UI-UI事件监听
    /// </summary>
    private void _initUIListener()
    {
        UI_UIEvtDic.Clear();
        var bindingFlag = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
        var mMethods = this.GetType().GetMethods(bindingFlag);
        foreach (var mMethodInfo in mMethods)
        {
            var mAttrObjs = mMethodInfo.GetCustomAttributes(typeof(UIListenerAttribute), false);
            if (mAttrObjs.Length > 0)
            {
                var mAttrObj = mAttrObjs[0] as UIListenerAttribute;
                var methodParameters = mMethodInfo.GetParameters();
                if (methodParameters.Length < 1)
                {
                    Debug.LogError("[UIListenerAttribute] 指定方法不符合规定，方法必须声明传参（EventArg） : " + mMethodInfo.Name, this);
                    return;
                }
                else if (methodParameters.Length == 1 & methodParameters[0].ParameterType == typeof(EventArg))
                {
                    Action<EventArg> action = (EventArg rArg) => { mMethodInfo.Invoke(this, new object[] { rArg }); };
                    //viewManager.EventManager.BindEvent(mAttrObj.EventCode, action);
                    AddEventToUIListener(mAttrObj.evtCode, action);
                }
                else
                {
                    Debug.LogError("[UIListenerAttribute] 指定方法不符合规定，只能声明传参（EventArg） : " + mMethodInfo.Name, this);
                    return;
                }
            }
        }
    }

    /// <summary>
    /// 绑定事件
    /// </summary>
    /// <param name="code"></param>
    /// <param name="action"></param>
    private void AddEventToUIListener(int code, Action<EventArg> action)
    {
        if (!this.UI_UIEvtDic.ContainsKey(code))
            this.UI_UIEvtDic[code] = new List<Action<EventArg>>();
        this.UI_UIEvtDic[code].Add(action);
    }


    /// <summary>
    /// 数据赋值
    /// </summary>
    /// <param name="args"></param>
    public virtual void DataInit(object[] args)
    {
        //该面板在初始化时的数据赋值

    }

    /// <summary>
    /// 面板打开时
    /// </summary>
    public virtual void OnOpenIng()
    {

        if (ifBlockTimeFlow)
        {
            Debug.Log(name + "调用时停");
            PanelManager.Instance.AddblockTimeFlowPage();
        }
        ShowPanelWithStyle(trans_content, showStyle);
        if (btn_close != null)
        {
            AddBtnListener(btn_close, Closed);
        }

        foreach (var item in DATA_UIEvtDic)
        {
            foreach (var action in item.Value)
            {
                EventCenter.AddDataListener(item.Key, action);
            }
        }

        foreach (var item in UI_UIEvtDic)
        {
            foreach (var action in item.Value)
            {
                EventCenter.AddUIListener(item.Key, action);
            }
        }
    }
    /// <summary>
    /// 面板关闭时
    /// </summary>
    public virtual void OnCloseIng()
    {
        if (ifBlockTimeFlow)
        {
            Debug.Log(name + "取消时停");
           PanelManager.Instance.RemoveblockTimeFlowPage();
        }
        foreach (var item in DATA_UIEvtDic)
        {
            foreach (var action in item.Value)
            {
                EventCenter.RemoveDataListener(item.Key, action);
            }
        }
        foreach (var item in UI_UIEvtDic)
        {
            foreach (var action in item.Value)
            {
                EventCenter.RemoveUIListener(item.Key, action);
            }
        }
    }
    /// <summary>
    /// 清理
    /// </summary>
    public virtual void Clear()
    {
        PanelManager.Instance.CloseAllSingleViewFromSelf(transform);
    }
    /// <summary>
    /// 关闭
    /// </summary>
    public void Closed()
    {
        //EventCenter.Call(EventDef.OnPanelClosed, this);
        PanelManager.Instance.OnPanelClosed(new object[] { this });
        OnCloseIng();
        RemoveAllBtnListener();
        HideObj(isTemp);
        Clear();
    }

    /// <summary>
    /// 关闭物体 进对象池(默认进永久）
    /// </summary>
    void HideObj(bool isTemp)
    {
        //string name = this.gameObject.name;
        //Debug.Log("关闭" + name);
        
        /*PoolType singleType = ObjectType;
        if (singleType == PoolType.None)
            singleType = (PoolType)Enum.Parse(typeof(PoolType), name);*/
        
        ObjectPoolManager.Instance.SaveObject(this.gameObject.name, gameObject, isTemp);
    }


    #region 事件
    /// <summary>
    /// 增加按钮点击事件
    /// </summary>
    /// <param name="btn"></param>
    /// <param name="listener"></param>
    protected void AddBtnListener(Button btn, UnityEngine.Events.UnityAction listener)
    {
        if (!btnListenerDic.ContainsKey(btn))
        {
            btn.onClick.AddListener(listener);
            //btn.onClick.AddListener(CheckRemovableGuideListener);
            //AudioManager.Instance.PlayOnshootAudio();
            btnListenerDic.Add(btn, listener);
            //Debug.Log("添加按钮监听" + btn.name);
        }
    }

    /*
     * /// <summary>
    /// 增加按钮点击事件
    /// </summary>
    /// <param name="btn"></param>
    /// <param name="listener"></param>
    protected void AddBtnListener(Button btn, UnityEngine.Events.UnityAction listener)
    {
        if (!btnListenerDic.ContainsKey(btn))
        {
            btn.onClick.AddListener(listener);
            btn.onClick.AddListener(CheckRemovableGuideListener);
            btnListenerDic.Add(btn, listener);
            //Debug.Log("添加按钮监听" + btn.name);
        }
    }*/
    
    
    /// <summary>
    /// 移除按钮点击事件
    /// </summary>
    void RemoveAllBtnListener()
    {
        curFocusedGuideId = 0;
        if (btnListenerDic != null && btnListenerDic.Count > 0)
        {
            foreach (KeyValuePair<Button, UnityEngine.Events.UnityAction> kv in btnListenerDic)
            {
                Button btn = kv.Key;
                UnityEngine.Events.UnityAction action = kv.Value;
                if (btn != null)
                {
                    btn.onClick.RemoveAllListeners();
                }
                //    btn.onClick.RemoveListener(action);

                //btn.onClick.AddListener(() => BtnScale(btn.transform));

            }
            btnListenerDic.Clear();

        }

        /*if (guideListenerList.Count > 0)
        {
            //Debug.LogError("还存在未完成的监听");
            foreach (var i in guideListenerList)
                GuideManager.Instance.RemoveNewGuideListener(i, false);
            guideListenerList.Clear();
        }*/
    }
    
    /*
    /// <summary>
    /// 指引监听
    /// </summary>
    /// <param name="ngsi">指引id</param>
    /// <param name="btn"></param>
    /// <param name="panel"></param>
    protected void AddGuideListener(GuideId ngsi, Button btn, PanelBase panel)
    {
        //NewGuideManager.Instance.RemoveNewGuideListener((int)ngsi, false);
        //btn.onClick.AddListener(() => NewGuideManager.Instance.RemoveNewGuideListener((int)ngsi, true));
        GuideManager.Instance.AddGuideListener(ngsi.ToInt32(), new GuideFocusInfo(new GameObject[] { btn.gameObject }, panel.gameObject));
        guideListenerList.Add(ngsi.ToInt32());
        
    }
    */
    
    
    /*/// <summary>
    /// 页面关闭后若没完成则取消
    /// </summary>
    /// <param name="ngsi"></param>
    public void RemoveGuideListener(GuideId ngsi)
    {
        GuideManager.Instance.RemoveNewGuideListener(ngsi.ToInt32(), false);
    }*/

    /*/// <summary>
    /// 指引监听
    /// </summary>
    /// <param name="ngsi">指引id</param>
    /// <param name="btn"></param>
    /// <param name="panel"></param>
    protected void AddGuideListener(GuideId ngsi, GameObject target, PanelBase panel)
    {
        //NewGuideManager.Instance.RemoveNewGuideListener((int)ngsi, false);
        //btn.onClick.AddListener(() => NewGuideManager.Instance.RemoveNewGuideListener((int)ngsi, true));
        GuideManager.Instance.AddGuideListener(ngsi.ToInt32(), new GuideFocusInfo(new GameObject[] { target }, panel.gameObject));
        guideListenerList.Add(ngsi.ToInt32());
    }*/

    /*/// <summary>
    /// 指引监听
    /// </summary>
    /// <param name="ngsi">指引id</param>
    /// <param name="btn"></param>
    /// <param name="panel"></param>
    protected void AddGuideListener(int ngsi, GameObject[] target, PanelBase panel)
    {
        //NewGuideManager.Instance.RemoveNewGuideListener((int)ngsi, false);
        //btn.onClick.AddListener(() => NewGuideManager.Instance.RemoveNewGuideListener((int)ngsi, true));
        GuideManager.Instance.AddGuideListener(ngsi, new GuideFocusInfo(target, panel.gameObject));
        guideListenerList.Add(ngsi);
    }*/

    /*/// <summary>
    /// 对于非强制引导，如果点击了该面板里的任何按钮，都将会完成这个引导
    /// </summary>
    /// <param name="ngsi"></param>
    void CheckRemovableGuideListener()
    {
        if (guideListenerList.Count > 0 && curFocusedGuideId != 0)
        {
            GuideSetting curSetting = DataManager.ReturnSettingByid<GuideSetting>(curFocusedGuideId);
            if (!curSetting.isForced.ToBool())
            {
                GuideManager.Instance.RemoveNewGuideListener(curFocusedGuideId, true);
            }
        }
    }*/
    
    
    /*/// <summary>
    /// 当前该panelbase正在进行新手引导
    /// </summary>
    /// <param name="ngsi"></param>
    public void OnNewGuideFocused(int ngsi)
    {
        curFocusedGuideId = ngsi;
    }
    public void OnNewGuideDefocused()
    {
        curFocusedGuideId = 0;
    }*/
    
    
    #endregion



    /// <summary>
    /// 页面显示方式
    /// </summary>
    /// <param name="trans">默认是页面本身</param>
    /// <param name="style"></param>
    void ShowPanelWithStyle(Transform trans, PanelShowStyle style)
    {
        if (btn_close != null)
            btn_close.interactable = false;
        switch (style)
        {
            case PanelShowStyle.None:
                if (btn_close != null)
                    btn_close.interactable = true;
                break;

            case PanelShowStyle.MoveToShowUp:
                trans.position = new Vector3(0, -3, 0);
                trans.DOMove(new Vector3(0, 2, 0), 0.2f).OnComplete(() =>
                {
                    trans.DOMove(new Vector3(0, -1, 0), 0.2f).OnComplete(() =>
                    {
                        trans.DOMove(new Vector3(0, 0, 0), 0.2f).OnComplete(() =>
                        {
                            if (btn_close != null)
                                btn_close.interactable = true;
                        });
                    });
                });
                break;
            case PanelShowStyle.ScaleToShowUp:
                trans.localScale = Vector2.zero;
                trans.DOScale(Vector2.one * PanelScaleVal, PanelScaleTime).OnComplete(() =>
                {
                    trans.DOScale(Vector2.one, PanelScaleBackTime).OnComplete(() =>
                    {
                        if (btn_close != null)
                            btn_close.interactable = true;
                    });
                });
                break;
            case PanelShowStyle.RotationToShowUp:
                break;
            default:
                break;
        }
    }


    private void OnDestroy()
    {

    }
}
